<?php
/**
 * @version 	$Id: fDispatcher.class.php 74 2010-03-17 06:48:21Z mylifeisskidrow@gmail.com $
 * @author 		$Author: mylifeisskidrow@gmail.com $
 * @copyright 	Copyright (c) 2010 Luu Trong Hieu. All right reserved.
 * @license 	GNU/GPL see license.php
 */

defined('IN_FLYWHEEL') or die('Restricted Access');

/**
 * Dispatcher
 * 
 * @package 	system
 * @subpackage 	event
 *
 */

class fDispatcher {
	protected $listeners = array();
	
	/**
	 * Construct new fDispatcher object
	 *
	 */
	private function __construct() {}
	
	/**
	 * Get Instance
	 *
	 * @return instance of fDispatcher
	 */
	public static function getInstance() {
		static $instance;
		if ($instance == null) {
			$instance = new fDispatcher();			
		}
		
		return $instance;
	}
	
	/**
	 * Connects a listener to a given event name.
	 *
	 * @param string  $name      An event name
	 * @param mixed   $listener  A PHP callable
	 */
	public function connect($name, $listener) {
		if (!isset($this->listeners[$name])) {
			$this->listeners[$name] = array();		
		}
		
		$this->listeners[$name][] = $listener;
	}
	
	/**
	 * Disconnect
	 * 	disconnect listener for a given event name
	 *
	 * @param unknown_type $name
	 * @param unknown_type $listener
	 */
	public function disconnect($name, $listener) {
		if (!isset($this->listeners[$name])) {
			return false;		
		}
		
		foreach ($this->listeners[$name] as $key => $callable) {
			if ($callable === $listener) {
				unset($this->listeners[$name][$key]);
			}
		}
		
		return true;
	}
	
	/**
	 * Return all listerners has association with event name
	 *
	 * @param string $name
	 * @return array
	 */
	public function getListeners($name) {
		if (!isset($this->listeners[$name])) {
			return array();
		}
		return $this->listeners[$name];		
	}
	
	/**
	 * Has Listener
	 * 	check exist listeners has assocation with event name
	 *
	 * @param string $name
	 * @return boolean
	 */
	public function hasListener($name) {
		return isset($this->listeners[$name]);
	}
	
	/**
	 * Filters a value by calling all listeners of a given event.
	 *
	 * @param  fEvent $event   A fEvent instance
	 * @param  mixed $value   The value to be filtered
	 *
	 * @return fEvent The fEvent instance
	 */
	public function filter(fEvent $event, $value) {
		foreach ($this->getListeners($event->getName()) as $listener) {
			$value = call_user_func_array($listener, array($event, $value));
		}
		$event->setValue($value);
		
		return $event;
	}
}